import java.io.*;
import java.math.BigInteger;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class DocumentSplitter {
    public static String calculateChecksum(File file) throws NoSuchAlgorithmException, IOException {
        // 获取 MD5 消息摘要算法的实例
        MessageDigest md = MessageDigest.getInstance("MD5");
        try (FileInputStream fis = new FileInputStream(file)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = fis.read(buffer))!= -1) {
                // 使用读取到的数据更新消息摘要
                md.update(buffer, 0, bytesRead);
            }
        }
        // 将消息摘要转换为 BigInteger 对象，再以十六进制字符串形式返回
        return new BigInteger(1, md.digest()).toString(16);
    }

    public static void splitFile(String sourceFilePath, String outputDir, Integer blockSize) throws IOException, URISyntaxException, NoSuchAlgorithmException {
        URL url = DocumentSplitter.class.getClassLoader().getResource(sourceFilePath);
        if (url == null) {
            throw new FileNotFoundException("无法找到资源: " + sourceFilePath);
        }
        File inputFile = new File(url.toURI());

        long fileSize = inputFile.length();
        long partSize = blockSize;

        byte[] buffer = new byte[blockSize];
        int bytesRead;

        try (FileInputStream fis = new FileInputStream(inputFile);
             BufferedInputStream bis = new BufferedInputStream(fis)) {
            for (int i = 0; i < 4; i++) {
                File outputFile = new File(outputDir, "part_" + i + ".bin");
                try (FileOutputStream fos = new FileOutputStream(outputFile);
                     BufferedOutputStream bos = new BufferedOutputStream(fos)) {
                    long bytesToRead = (i < 3)? partSize : (fileSize - (3 * partSize));
                    while (bytesToRead > 0 && (bytesRead = bis.read(buffer))!= -1) {
                        long bytesToWrite = Math.min(bytesRead, bytesToRead);
                        bos.write(buffer, 0, (int) bytesToWrite);
                        bytesToRead -= bytesRead;
                    }
                }
                // 计算并记录校验码
                String checksum = calculateChecksum(outputFile);
                try (FileOutputStream fos = new FileOutputStream(outputFile, true);
                     BufferedOutputStream bos = new BufferedOutputStream(fos)) {
                    bos.write(("CHECKSUM:" + checksum + "\n").getBytes());
                }
            }
        }
    }

    public static void main(String[] args) {
        try {
            splitFile("twoParties.png", "output", 20480);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }
}